package com.qing.microservices.shirostudy.realm;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qing.microservices.shirostudy.entity.Authority;
import com.qing.microservices.shirostudy.entity.Role;
import com.qing.microservices.shirostudy.entity.User;
import com.qing.microservices.shirostudy.service.IRoleService;
import com.qing.microservices.shirostudy.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author guoqf
 */
@Slf4j
public class CustomizedRealm extends AuthorizingRealm {

    @Autowired
    private IUserService userService;

    @Autowired
    private IRoleService roleService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
        log.info("校验用户[{}]授权", primaryPrincipal);
        // 查询账号
        User user = userService.queryByUsername(primaryPrincipal);

        // 查询用户角色
        List<Role> roleList = user != null ? userService.queryUserRoles(user.getId()) : null;
        if (CollectionUtils.isNotEmpty(roleList)) {
            // 使用Shiro提供的授权信息类
            SimpleAuthorizationInfo authzInfo = new SimpleAuthorizationInfo();

            // 授权信息设置角色列表
            Set<String> roles = roleList.stream().map(Role::getName).collect(Collectors.toSet());
            log.info("查询到角色{}", roles);
            authzInfo.setRoles(roles);

            // 查询用户权限
            List<Authority> authorityList = roleService.queryAuthorityList(roleList.stream().map(Role::getId).collect(Collectors.toList()));
            if (CollectionUtils.isNotEmpty(authorityList)) {

                // 授权信息设置权限列表
                Set<String> permissions = authorityList.stream().map(Authority::getName).collect(Collectors.toSet());
                log.info("查询到权限{}", permissions);
                authzInfo.setStringPermissions(permissions);
            }
            return authzInfo;
        }
        log.info("未查询到用户[{}]角色信息", primaryPrincipal);
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 获取页面输入的用户名
        String principal = (String) authenticationToken.getPrincipal();
        log.info("对用户[{}]认证", principal);

        // 根据用户名查询账号
        User user = userService.getOne(new QueryWrapper<User>().lambda().eq(User::getUsername, principal));
        if (user != null) {
            log.info("查询到用户[{}]信息", principal);
            // 使用Shiro提供的认证信息类
            return new SimpleAuthenticationInfo(user.getUsername(), user.getPasswd(), ByteSource.Util.bytes(user.getSalt()), this.getName());
        }

        return null;
    }
}
